//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0
/********************************************************
    说明：
    1、这个链表是基于 FreeRTOS 版本里的链表修改而来。
    2、链表创建时已包含一个链表节点。该项的值是所能存储的最大可能值，因此它始终位于链表末尾并充当标记。
    3、链表成员Head始终指向此标记，尽管它位于链表尾部。这是因为尾部包含一个回指链表真正头部的指针。
    4、除了其自身的值之外，每个链表节点还包含一个指向下一个链表节点的指针（Next）、一个指向其所在链表的指针（Container），以及一个指向包含该链表节点的对象的指针。
    5、后两个指针的存在是为了提高链表操作的效率。实际上，包含链表节点的对象与链表节点本身之间存在双向链接。
**********************************************************/

#ifndef __RTOS_LIST_H__
#define __RTOS_LIST_H__

#ifdef __cplusplus
extern "C" {
#endif


typedef long BaseType_t;
typedef unsigned long UBaseType_t;

#ifndef portMAX_DELAY
	#define portMAX_DELAY  0xffffffffUL
#endif

#define pdFALSE			( ( BaseType_t ) 0 )
#define pdTRUE			( ( BaseType_t ) 1 )

#define pdPASS			( pdTRUE )
#define pdFAIL			( pdFALSE )



/*
 * 链表定义
 */
struct LIST_NODE
{
	UBaseType_t NodeValue;		    /* 用于排序的键值 */
	struct LIST_NODE * Next;		/* 指向下一个节点 */
	struct LIST_NODE * Previous;	/* 指向前一个节点 */
	void * Owner;					/* 指向拥有该节点的对象（如任务控制块） */
	void * Container;				/* 指向该节点所在的链表 */
};
typedef struct LIST_NODE ListNode_t;

struct MINI_LIST_NODE
{
	UBaseType_t NodeValue;			/* 用于排序的键值 */
	struct LIST_NODE * Next;        /* 指向下一个节点 */
	struct LIST_NODE * Previous;    /* 指向前一个节点 */
};
typedef struct MINI_LIST_NODE MiniListNode_t;

typedef struct LIST
{
	UBaseType_t NumberOfNodes;      /* 链表里的节点数量 */
	ListNode_t * Index;			    /* 当前遍历位置的指针 */
	MiniListNode_t ListEnd;			/* 链表尾部标记（头部节点） */
} LIST_t;

/*
 * 设置链表节点的所有者
 */
#define ListSET_LIST_NODE_OWNER( ListNode, Owner )		( ( ListNode )->Owner = ( void * ) ( Owner ) )

/*
 * 获取链表节点的所有者
 */
#define ListGET_LIST_NODE_OWNER( ListNode )	( ( ListNode )->Owner )

/*
 * 设置链表节点的值。在大多数情况下，该值用于按降序对链表节点进行排序
 */
#define ListSET_LIST_NODE_VALUE( ListNode, Value )	( ( ListNode )->NodeValue = ( Value ) )

/*
 * 用于检索链表节点的值。该值可以代表任何内容，例如任务的优先级，或者任务应解除阻塞的时间。
 */
#define ListGET_LIST_NODE_VALUE( ListNode )	( ( ListNode )->NodeValue )

/*
 * 获取链表第一个节点的值
 */
#define ListGET_NODE_VALUE_OF_HEAD_ENTRY( List )	( ( ( List )->ListEnd ).Next->NodeValue )

/*
 * 返回链表的第一个节点
 */
#define ListGET_HEAD_ENTRY( List )	( ( ( List )->ListEnd ).Next )

/*
 * 返回链表节点的下一个节点
 */
#define ListGET_NEXT( ListNode )	( ( ListNode )->Next )

/*
 * 返回链表尾部标记的链表节点
 */
#define ListGET_END_MARKER( List )	( ( ListNode_t const * ) ( &( ( List )->ListEnd ) ) )

/*
 * 判断链表是否为空。仅当链表为空时，该宏的值才为真。
 */

#define ListLIST_IS_EMPTY( List )	( ( BaseType_t ) ( ( List )->NumberOfNodes == ( UBaseType_t ) 0 ) )
/*
 * 返回链表中链表节点的数目
 */
#define ListCURRENT_LIST_LENGTH( List )	( ( List )->NumberOfNodes )

/*
 * 获取链表中下一个链表节点的访问函数.
 *
 * 链表成员Index用于遍历链表节点。调用listGET_OWNER_OF_NEXT_ENTRY会将Index增加到链表节点中的下一个，并返回该项的Owner参数。因此，通过多次调用此函数，可以遍历链表中包含的每个节点。
 *
 * 链表节点的Owner参数是一个指向拥有该链表节点的对象的指针。在调度器中，这通常是一个任务控制块。Owner参数实际上在链表节点与其所有者之间创建了一种双向链接。
 *
 * @param TCB 链表节点的访问函数
 * @param List 链表节点所在的链表
 *
 */
#define ListGET_OWNER_OF_NEXT_ENTRY( TCB, List )									\
{																					\
LIST_t * const ConstList = ( List );												\
	/* 将索引增加到下一个节点并返回该节点，确保我们不会返回链表末尾使用的标记 */      	  \
	( ConstList )->Index = ( ConstList )->Index->Next;							    \
	if( ( void * ) ( ConstList )->Index == ( void * ) &( ( ConstList )->ListEnd ) )	\
	{																				\
		( ConstList )->Index = ( ConstList )->Index->Next;						    \
	}																				\
	( TCB ) = ( ConstList )->Index->Owner;											\
}


/*
 * 获取链表中第一个链表节点的访问函数。链表通常按链表节点值升序排序.
 *
 * 这个函数返回链表中第一个节点的Owner成员.
 * 链表节点的Owner参数是一个指向拥有该链表节点的对象的指针。
 * Owner参数实际上在链表节点与其所有者之间创建了一种双向链接.
 *
 * @param List 链表节点所在的链表.
 *
 */
#define ListGET_OWNER_OF_HEAD_ENTRY( List )  ( (&( ( List )->ListEnd ))->Next->Owner )

/*
 * 检查链表节点是否在链表中。
 *
 * @param List 链表.
 * @param ListNode 链表节点.
 * @return 如果链表节点在链表中为pdTRUE，否则为pdFALSE.
 */
#define ListIS_CONTAINED_WITHIN( List, ListNode ) ( ( BaseType_t ) ( ( ListNode )->Container == ( void * ) ( List ) ) )

/*
 * 返回包含链表节点所在的的链表.
 *
 * @param ListNode 正在被查询的链表节点.
 * @return 链表节点的List_t对象的指针
 */
#define ListLIST_NODE_CONTAINER( ListNode ) ( ( ListNode )->Container )

/*
 * 粗略的方法来判断一个链表是否已初始化，因为在调用ListInitialise()函数时，List->ListEnd.NodeValue 会被设置为portMAX_DELAY.
 */
#define ListLIST_IS_INITIALISED( List ) ( ( List )->ListEnd.NodeValue == portMAX_DELAY )

/*
 * 必须在使用链表之前调用此函数！这将初始化链表结构的所有成员，并将ListEnd项插入到链表中，作为链表末尾的标记.
 *
 * @param List 指向正在初始化的链表的指针.
 *
 */
void ListInitialise( LIST_t * const List );

/*
 * 必须在使用链表节点之前调用此函数。这会将链表节点设置为空，以便该节点不会认为它已包含在链表中.
 *
 * @param Node 指向正在初始化的链表节点的指针.
 *
 */
void ListInitialiseNode( ListNode_t * const Node );

/*
 * 将链表节点插入到链表中。该链表节点将根据其节点值（按节点值降序）确定的位置插入到链表中.
 *
 * @param List 要插入该链表节点的链表.
 *
 * @param NewListNode 要放入链表中的节点.
 *
 */
void ListInsert( LIST_t * const List, ListNode_t * const NewListNode );

/*
 * 将链表节点插入到链表最后中。该节点将被插入到最后位置，使得在多次调用listGET_OWNER_OF_NEXT_ENTRY返回的链表中，它将是最后节点.
 *
 * 链表成员Index用于遍历链表节点。调用listGET_OWNER_OF_NEXT_ENTRY会将Index增加到链表中的下一个节点.
 * 使用vListInsertEnd将一个节点放入链表中，实际上是将该链表节点放入Index所指向的链表位置。这意味着，在Index参数再次指向正在插入的节点之前，链表中的其他每个链表节点都将由listGET_OWNER_OF_NEXT_ENTRY返回。
 *
 * @param List 要插入节点的链表.
 *
 * @param NewListNode 要插入到链表中的链表节点.
 *
 */
void ListInsertEnd( LIST_t * const List, ListNode_t * const NewListNode );

/*
 * 从链表中移除一个节点。链表节点有一个指向它所在链表的指针，所以只需将链表节点传入给函数.
 *
 * @param ListRemove 要移除的链表节点。该链表节点将从其 Container 参数指向的链表中自行移除.
 *
 * @return 链表节点被移除后，链表中剩余的节点数量.
 *
 */
UBaseType_t ListRemove( ListNode_t * const NodeToRemove );

#ifdef __cplusplus
}
#endif

#endif

